package com.example;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.*;

public class ExpenseTracker extends JFrame {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/expense_tracker";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "050726";

    private JTextField amountField, categoryField, descriptionField;
    private JComboBox<String> categoryComboBox;
    private JTextArea expenseListArea;

    public ExpenseTracker() {
        initializeUI();
        createTables();
        loadCategories();
    }

    private void initializeUI() {
        setTitle("个人消费追踪系统");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        JPanel mainPanel = new JPanel(new BorderLayout());
        mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // 输入面板
        JPanel inputPanel = new JPanel(new GridLayout(5, 2, 10, 10));
        inputPanel.setBorder(BorderFactory.createTitledBorder("添加新消费"));

        JLabel amountLabel = new JLabel("金额:");
        amountField = new JTextField();

        JLabel categoryLabel = new JLabel("类别:");
        categoryComboBox = new JComboBox<>();

        JLabel newCategoryLabel = new JLabel("新类别:");
        categoryField = new JTextField();

        JLabel descriptionLabel = new JLabel("描述:");
        descriptionField = new JTextField();

        JButton addButton = new JButton("添加消费");
        addButton.addActionListener(new AddExpenseListener());

        JButton addCategoryButton = new JButton("添加类别");
        addCategoryButton.addActionListener(new AddCategoryListener());

        inputPanel.add(amountLabel);
        inputPanel.add(amountField);
        inputPanel.add(categoryLabel);
        inputPanel.add(categoryComboBox);
        inputPanel.add(newCategoryLabel);
        inputPanel.add(categoryField);
        inputPanel.add(descriptionLabel);
        inputPanel.add(descriptionField);
        inputPanel.add(addButton);
        inputPanel.add(addCategoryButton);

        // 消费列表面板
        JPanel listPanel = new JPanel(new BorderLayout());
        listPanel.setBorder(BorderFactory.createTitledBorder("消费记录"));

        expenseListArea = new JTextArea();
        expenseListArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(expenseListArea);

        listPanel.add(scrollPane, BorderLayout.CENTER);

        // 统计面板
        JPanel statsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        statsPanel.setBorder(BorderFactory.createTitledBorder("消费统计"));

        JButton monthlyReportButton = new JButton("月度报表");
        monthlyReportButton.addActionListener(new MonthlyReportListener());

        JButton categoryReportButton = new JButton("类别分析");
        categoryReportButton.addActionListener(new CategoryReportListener());

        statsPanel.add(monthlyReportButton);
        statsPanel.add(categoryReportButton);

        mainPanel.add(inputPanel, BorderLayout.NORTH);
        mainPanel.add(listPanel, BorderLayout.CENTER);
        mainPanel.add(statsPanel, BorderLayout.SOUTH);

        add(mainPanel);
        refreshExpenseList();
    }

    private void createTables() {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            // 创建类别表
            String createCategoryTableSQL = "CREATE TABLE IF NOT EXISTS categories (" +
                    "id INT PRIMARY KEY AUTO_INCREMENT," +
                    "name VARCHAR(50) NOT NULL UNIQUE" +
                    ")";

            // 创建消费记录表
            String createExpenseTableSQL = "CREATE TABLE IF NOT EXISTS expenses (" +
                    "id INT PRIMARY KEY AUTO_INCREMENT," +
                    "amount DECIMAL(10, 2) NOT NULL," +
                    "category_id INT NOT NULL," +
                    "description VARCHAR(255)," +
                    "date TIMESTAMP DEFAULT CURRENT_TIMESTAMP," +
                    "FOREIGN KEY (category_id) REFERENCES categories(id)" +
                    ")";

            try (Statement stmt = conn.createStatement()) {
                stmt.executeUpdate(createCategoryTableSQL);
                stmt.executeUpdate(createExpenseTableSQL);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "数据库连接失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void loadCategories() {
        categoryComboBox.removeAllItems();
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT * FROM categories")) {

            while (rs.next()) {
                categoryComboBox.addItem(rs.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private void refreshExpenseList() {
        expenseListArea.setText("");
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(
                     "SELECT e.id, e.amount, c.name AS category, e.description, e.date " +
                             "FROM expenses e " +
                             "JOIN categories c ON e.category_id = c.id " +
                             "ORDER BY e.date DESC")) {

            expenseListArea.append(String.format("%-5s %-10s %-15s %-25s %-20s%n",
                    "ID", "金额", "类别", "描述", "日期"));
            expenseListArea.append("------------------------------------------------------------------------\n");

            while (rs.next()) {
                expenseListArea.append(String.format("%-5d %-10.2f %-15s %-25s %-20s%n",
                        rs.getInt("id"),
                        rs.getDouble("amount"),
                        rs.getString("category"),
                        rs.getString("description"),
                        rs.getTimestamp("date")));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private int getCategoryId(String categoryName) {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM categories WHERE name = ?")) {

            pstmt.setString(1, categoryName);
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    return rs.getInt("id");
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return -1;
    }

    private class AddExpenseListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            try {
                double amount = Double.parseDouble(amountField.getText());
                String category = (String) categoryComboBox.getSelectedItem();
                String description = descriptionField.getText();

                if (category == null || category.isEmpty()) {
                    JOptionPane.showMessageDialog(ExpenseTracker.this, "请选择一个类别", "错误", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                int categoryId = getCategoryId(category);
                if (categoryId == -1) {
                    JOptionPane.showMessageDialog(ExpenseTracker.this, "类别不存在", "错误", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                String sql = "INSERT INTO expenses (amount, category_id, description) VALUES (?, ?, ?)";
                try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
                     PreparedStatement pstmt = conn.prepareStatement(sql)) {

                    pstmt.setDouble(1, amount);
                    pstmt.setInt(2, categoryId);
                    pstmt.setString(3, description);
                    pstmt.executeUpdate();
                }

                amountField.setText("");
                descriptionField.setText("");
                refreshExpenseList();
                JOptionPane.showMessageDialog(ExpenseTracker.this, "消费记录已添加", "成功", JOptionPane.INFORMATION_MESSAGE);
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(ExpenseTracker.this, "请输入有效的金额", "错误", JOptionPane.ERROR_MESSAGE);
            } catch (SQLException ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(ExpenseTracker.this, "数据库错误: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private class AddCategoryListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            String newCategory = categoryField.getText().trim();
            if (newCategory.isEmpty()) {
                JOptionPane.showMessageDialog(ExpenseTracker.this, "类别名称不能为空", "错误", JOptionPane.ERROR_MESSAGE);
                return;
            }

            try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
                 PreparedStatement pstmt = conn.prepareStatement("INSERT INTO categories (name) VALUES (?)")) {

                pstmt.setString(1, newCategory);
                pstmt.executeUpdate();
                categoryField.setText("");
                loadCategories();
                JOptionPane.showMessageDialog(ExpenseTracker.this, "类别已添加", "成功", JOptionPane.INFORMATION_MESSAGE);
            } catch (SQLException ex) {
                if (ex.getErrorCode() == 1062) { // 唯一约束冲突
                    JOptionPane.showMessageDialog(ExpenseTracker.this, "类别已存在", "错误", JOptionPane.ERROR_MESSAGE);
                } else {
                    ex.printStackTrace();
                    JOptionPane.showMessageDialog(ExpenseTracker.this, "数据库错误: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                }
            }
        }
    }

    private class MonthlyReportListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
                 Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery(
                         "SELECT MONTH(date) AS month, SUM(amount) AS total " +
                                 "FROM expenses " +
                                 "GROUP BY MONTH(date) " +
                                 "ORDER BY MONTH(date)")) {

                StringBuilder report = new StringBuilder();
                report.append("月度消费报表:\n");
                report.append("-----------------\n");
                report.append("月份\t总金额\n");
                report.append("-----------------\n");

                while (rs.next()) {
                    report.append(String.format("%d月\t%.2f\n",
                            rs.getInt("month"),
                            rs.getDouble("total")));
                }

                JOptionPane.showMessageDialog(ExpenseTracker.this, report.toString(), "月度报表", JOptionPane.INFORMATION_MESSAGE);
            } catch (SQLException ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(ExpenseTracker.this, "数据库错误: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private class CategoryReportListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
                 Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery(
                         "SELECT c.name AS category, SUM(e.amount) AS total " +
                                 "FROM expenses e " +
                                 "JOIN categories c ON e.category_id = c.id " +
                                 "GROUP BY c.name " +
                                 "ORDER BY total DESC")) {

                StringBuilder report = new StringBuilder();
                report.append("类别消费分析:\n");
                report.append("-----------------\n");
                report.append("类别\t总金额\n");
                report.append("-----------------\n");

                while (rs.next()) {
                    report.append(String.format("%-15s %.2f\n",
                            rs.getString("category"),
                            rs.getDouble("total")));
                }

                JOptionPane.showMessageDialog(ExpenseTracker.this, report.toString(), "类别分析", JOptionPane.INFORMATION_MESSAGE);
            } catch (SQLException ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(ExpenseTracker.this, "数据库错误: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            ExpenseTracker app = new ExpenseTracker();
            app.setVisible(true);
        });
    }
}    